package com.yeyuanqi.hottop.shiro;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yeyuanqi.hottop.entity.SysUser;
import com.yeyuanqi.hottop.service.SysUserService;
import com.yeyuanqi.hottop.untils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;


/**
 * <P>自定义Realm</P>
 *
 * @author yeyuanqi
 * @date  2022/02/27
 */
@Slf4j
@Component
public class AccountRealm extends AuthorizingRealm {

    @Lazy
    @Autowired
    JwtUtils jwtUtils;

    @Lazy
    @Autowired
    private SysUserService userService;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 授权 无用
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//        return new SimpleAuthorizationInfo();
        log.info("执行doGetAuthorizationInfo方法进行授权");
//        String username = JwtUtil.getUsername(principalCollection.toString());
        log.info(principals.toString());
//        log.info("登录的用户:" + username);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        AccountProfile accountProfile = (AccountProfile)principals.getPrimaryPrincipal();
        String[] roles = accountProfile.getRole().split(",");
        log.info("roles");
        for(String role : roles){
            info.addRole(role);
            if( role.equals("role_root")){
                info.addStringPermission("user:read");
                info.addStringPermission("user:create");
                info.addStringPermission("user:update");
            }
            else if( role.equals("role_user")){
                info.addStringPermission("user:read");
                info.addStringPermission("user:create");
            }
        }

        return info;
    }

    /**
     * 登录认证  无用
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        JwtToken jwt = (JwtToken) token;
        log.info("jwt----------------->{}", jwt);
        //获取用户账号
        String userId = (String) jwtUtils.getClaimByToken((String) jwt.getPrincipal()).get("userId");
        String username = (String) jwtUtils.getClaimByToken((String) jwt.getPrincipal()).get("username");
//        String username = token.getPrincipal().toString();
//        SysUser user = userService.getOne(new QueryWrapper<SysUser>().eq("user_name", username));
        SysUser user = userService.getById(Long.parseLong(userId));
//        SysUser user = shiroService.getUserByUsername(username);
        if (user == null) {
            throw new UnknownAccountException("账户不存在！");
        }
        if ("1".equals(user.getStatus())) {
            throw new LockedAccountException("账户已被锁定！");
        }
        if(!user.getUserName().equals(username)){
            throw new UnknownAccountException("userId与username不一致");
        }
        if (!ObjectUtils.isEmpty(user)) {

            /**
             * 四个参数
             * principal：认证的实体信息，可以是username，也可以是数据库表对应的用户的实体对象
             * credentials：数据库中的密码（经过加密的密码）
             * credentialsSalt：盐值（使用用户名）
             * realmName：当前realm对象的name，调用父类的getName()方法即可
             */

            AccountProfile profile = new AccountProfile();
            //知道它的身份 principals
            BeanUtil.copyProperties(user, profile);
            log.info("profile----------------->{}", profile.toString());
            return new SimpleAuthenticationInfo(profile, jwt.getCredentials(), getName());

//            String realmName = getName();
//            String credentials = user.getPassword();
//            ByteSource credentialsSalt = ByteSource.Util.bytes(username);
//
//            return new SimpleAuthenticationInfo(username, credentials, credentialsSalt, realmName);
        }
        return null;
    }
}